import javax.swing.*;
import javax.swing.plaf.nimbus.NimbusLookAndFeel;
import java.awt.*;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.List;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Function;
import java.util.stream.Stream;

/**
 * @author cwq
 */
public class Main {
    
    public static final String tempFilePath = System.getProperty("java.io.tmpdir");
    
    private static final Dimension windowSize = Toolkit.getDefaultToolkit().getScreenSize();
    
    private static final java.util.List<String> nameList = new ArrayList<>();
    private static final JLabel label = new JLabel("未知", JLabel.CENTER);
    private static final JButton startBtn = new JButton("开始");
    private static final JButton stopBtn = new JButton("结束");
    
    private static volatile boolean flag;
    private static String currentDataSourceType = FuncEnum.EXCEL.getType();
    
    private static final JFrame frame = new JFrame();
    private static final JDesktopPane desktopPane = new JDesktopPane();
    
    private static final ExecutorService executorService = Executors.newSingleThreadExecutor();
    
    public static void main(String[] args) throws Exception {
        //UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        UIManager.setLookAndFeel(NimbusLookAndFeel.class.getName());
        
        frame.setSize((int) (2 * windowSize.getWidth() / 3), (int) (2 * windowSize.getHeight() / 3));
        frame.setTitle("随机点名程序");
        frame.setResizable(false);
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setContentPane(desktopPane);
        
        JMenuBar menuBar = new JMenuBar();
        JMenu mainMenu = new JMenu("文件");
        menuBar.add(mainMenu);
        JMenu loadMenu = new JMenu("加载");
        mainMenu.add(loadMenu);
        
        Map<String, ActionListener> actionsMap = new HashMap<>(3);
        actionsMap.put("excel数据", event -> {
            currentDataSourceType = FuncEnum.EXCEL.getType();
            JFileChooser fileChooser = new JFileChooser();
            fileChooser.setCurrentDirectory(new File("."));
            int openFileRes = fileChooser.showDialog(frame, "打开Excel文件");
            if (openFileRes == JFileChooser.APPROVE_OPTION) {
                File selectedFile = fileChooser.getSelectedFile();
                try {
                    Files.copy(Paths.get(selectedFile.getAbsolutePath()),
                            Paths.get(tempFilePath + "student.xls"),
                            StandardCopyOption.REPLACE_EXISTING);
                } catch (IOException e) {
                    e.printStackTrace();
                    JOptionPane.showMessageDialog(frame, "Excel文件加载失败", "错误", JOptionPane.ERROR_MESSAGE);
                }
                loadNameList(currentDataSourceType);
            }
        });
        actionsMap.put("mysql数据", event -> {
            currentDataSourceType = FuncEnum.MYSQL.getType();
            JInternalFrame[] allFrames = desktopPane.getAllFrames();
            if (Arrays.stream(allFrames).noneMatch(innerFrame -> innerFrame.getName().equals(MysqlFrame.NAME))) {
                JInternalFrame mysqlFrame = new MysqlFrame(desktopPane);
                try (Stream<String> lines = Files.lines(Paths.get(tempFilePath + "mysql.conf"))) {
                    Optional<String> firstLine = lines.findFirst();
                    if (firstLine.isPresent() && UiBuilder.isNotBlank(firstLine.get())) {
                        String[] connectPropStr = firstLine.get().split(",");
                        ((JTextField) UiBuilder.componentCacheMap.get("MysqlFrame.hostField")).setText(connectPropStr[0]);
                        ((JTextField) UiBuilder.componentCacheMap.get("MysqlFrame.usernameField")).setText(connectPropStr[1]);
                        ((JTextField) UiBuilder.componentCacheMap.get("MysqlFrame.passwordField")).setText(connectPropStr[2]);
                        ((JTextField) UiBuilder.componentCacheMap.get("MysqlFrame.dbNameField")).setText(connectPropStr[3]);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                mysqlFrame.setVisible(true);
            }
        });
        actionsMap.put("sqlite数据", event -> {
            currentDataSourceType = FuncEnum.SQLITE.getType();
            JInternalFrame[] allFrames = desktopPane.getAllFrames();
            if (Arrays.stream(allFrames).noneMatch(innerFrame -> innerFrame.getName().equals(SqliteFrame.NAME))) {
                JInternalFrame sqliteFrame = new SqliteFrame(desktopPane);
                sqliteFrame.setVisible(true);
            }
        });
        for (String menuStr : actionsMap.keySet()) {
            JMenuItem menuItem = new JMenuItem(menuStr);
            menuItem.addActionListener(actionsMap.get(menuStr));
            loadMenu.add(menuItem);
        }
        frame.setJMenuBar(menuBar);
        
        desktopPane.setLayout(null);
        JPanel centerPane = new JPanel(new BorderLayout());
        centerPane.setBackground(Color.WHITE);
        centerPane.setBounds(frame.getWidth() / 4, frame.getHeight() / 4, frame.getWidth() / 2, frame.getHeight() / 2);
        desktopPane.add(centerPane, BorderLayout.CENTER);
        
        Font font = new Font("宋体", Font.BOLD, 35);
        label.setFont(font);
        centerPane.add(label, BorderLayout.NORTH);
        
        JPanel panel = new JPanel(new BorderLayout());
        startBtn.setFont(font.deriveFont(20f));
        startBtn.addActionListener(event -> startLoop());
        panel.add(startBtn, BorderLayout.WEST);
        stopBtn.setFont(font.deriveFont(20f));
        stopBtn.addActionListener(event -> stopLoop());
        panel.add(stopBtn, BorderLayout.EAST);
        panel.setBackground(Color.WHITE);
        centerPane.add(panel, BorderLayout.SOUTH);
        frame.setVisible(true);
    }
    
    private static void startLoop() {
        if (nameList.size() == 0) {
            JOptionPane.showMessageDialog(frame, "数据为空", "错误", JOptionPane.ERROR_MESSAGE);
            return;
        }
        flag = true;
        executorService.submit(() -> {
            while (flag) {
                int randNum = (int) (Math.floor((Math.random()) * nameList.size()));
                label.setText(nameList.get(randNum));
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    System.out.println("error");
                }
            }
        });
    }
    
    private static void stopLoop() {
        flag = false;
        String currentName = label.getText();
        nameList.stream().filter(item -> item.equals(currentName)).findFirst().ifPresent(nameList::remove);
    }
    
    private static void loadNameList(String type) {
        Function<String, List<String>> func = FuncEnum.getFuncByType(type);
        nameList.clear();
        if (FuncEnum.EXCEL.getType().equals(type)) {
            try {
                Path source = Paths.get("student.xls");
                if (Files.exists(source)) {
                    Files.copy(source, Files.newOutputStream(Paths.get(tempFilePath + "student.xls")));
                }
                nameList.addAll(func.apply(tempFilePath + "student.xls"));
            } catch (Exception ex) {
                JOptionPane.showMessageDialog(frame, "默认数据文件不存在", "警告", JOptionPane.WARNING_MESSAGE);
            }
        } else if (FuncEnum.MYSQL.getType().equals(type)) {
            try (Stream<String> lines = Files.lines(Paths.get(tempFilePath + "mysql.conf"))) {
                Optional<String> firstLine = lines.findFirst();
                assert func != null;
                nameList.addAll(func.apply(firstLine.get()));
            } catch (IOException e) {
                JOptionPane.showMessageDialog(frame, "加载Mysql数据库配置文件失败", "警告", JOptionPane.WARNING_MESSAGE);
            }
        } else if (FuncEnum.SQLITE.getType().equals(type)) {
            try (Stream<String> lines = Files.lines(Paths.get(tempFilePath + "sqlite.conf"))) {
                Optional<String> firstLine = lines.findFirst();
                assert func != null;
                nameList.addAll(func.apply(firstLine.get()));
            } catch (IOException e) {
                JOptionPane.showMessageDialog(frame, "加载Sqlite数据库配置文件失败", "警告", JOptionPane.WARNING_MESSAGE);
            }
        }
    }
    
}
